import 'dart:typed_data';

import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/euc_message_factory.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

class E25MessageFactory extends EucLorinSpecialMessageFactory<_E25Cmd>
    implements
        BMSLogMsgFactoryTrait<LorinMessage>,
        FullBMSFeatureMsgFactoryTrait<LorinMessage> {
  E25MessageFactory(ProductProperty productProperty) : super(productProperty);

  @override
  void initCompact(int apiVersion, VersionWrapper version) {
    compact = null;
    // 默认用V2 CMD
    compact ??= _E25CmdV2();
  }

  LorinMessage genSetSpeedUnitMsg(int unit) {
    return genSpecialOne2OneWriteMsg(
        (compact! as _E25CmdV2).speedUnitCmd(), ByteUtil.num2BytesLe(unit, 1));
  }

  LorinMessage genAutoScreenOffOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        compact!.autoScreenOffCmd(), ByteUtil.bool2Bytes(on));
  }

  LorinMessage genDaytimeRunningLightMsg(bool on) {
    return genSpecialOne2OneWriteMsg(
        (compact! as _E25CmdV2).daytimeRunningLightCmd(),
        ByteUtil.bool2Bytes(on));
  }

  @override
  LorinMessage genHeadlightOnOffMsg(
      {bool? on, bool? lowBeamOn, bool? highBeamOn, int? source, int? target}) {
    Uint8ClampedList bytes = Uint8ClampedList(2);
    bytes[0] = on == true ? 1 : 0;
    bytes[1] = on == true ? 1 : 0;
    return genSpecialOne2OneWriteMsg(compact!.headlightOnOffCmd(), bytes);
  }

  @override
  LorinMessage genSetLightEffectModeMsg(int mode,
      [Uint8ClampedList? param, int? source, int? target]) {
    if (param == null)
      throw Exception(
          "Param [param] for 'genSetLightEffectModeMsg' must be set in E25. mode: $mode");
    return genSpecialOne2OneWriteMsg(compact!.lightEffectModeCmd(),
        ByteUtil.buildBytes(ByteUtil.num2BytesLe(mode, 1), param));
  }

  LorinMessage genRequestLightEffectMsg() {
    return genSpecialOne2OneReadMsg(compact!.lightEffectModeCmd());
  }

  LorinMessage genRequestCurrentLightEffectIdMsg() {
    return genSpecialOne2OneReadMsg(compact!.lightEffectIdCmd());
  }

  LorinMessage genDisableChargeDangerAlertMsg() {
    return genSpecialOne2OneWriteMsg(
        compact!.disableChargeDangerAlertCmd(), Uint8ClampedList.fromList([1]));
  }

  LorinMessage genSetWarningLimitSpeedMsg(int speed1, int speed2) {
    Uint8ClampedList param = Uint8ClampedList(4);
    ByteUtil.num2BytesLe(speed1, 2, param, 0);
    ByteUtil.num2BytesLe(speed2, 2, param, 2);
    return genSpecialOne2OneWriteMsg(compact!.warningLimitSpeedCmd(), param);
  }

  @override
  LorinMessage genRequestBMSRealTimeInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsRealTimeInfoCmd());
  }

  @override
  LorinMessage genRequestBMSFixedInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsFixedInfoCmd());
  }

  @override
  LorinMessage genRequestBMSCellsVoltageInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsCellsVoltageCmd());
  }

  @override
  LorinMessage genRequestBMSDateMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsDateCmd());
  }

  @override
  LorinMessage genRequestBMSLogMsg(int target, int index) {
    return genSpecialMany2ManyReadMsg(
        null, target, compact!.bmsLogCmd(), ByteUtil.num2BytesLe(index, 4));
  }

  @override
  LorinMessage genRequestBMSLogCountMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, compact!.bmsLogCmd(),
        ByteUtil.num2BytesLe(0xFFFFFFFF, 4));
  }
}

abstract class _E25Cmd extends EucCmdCompact implements FullBMSFeatureCmdTrait {
  int autoLowHighBeamOnOffCmd();

  int autoScreenOffCmd();

  int speedThrOfLowHighBeamSwitchCmd();

  int bmsLogCmd();

  int disableChargeDangerAlertCmd() {
    return 0;
  }

  int warningLimitSpeedCmd() {
    return 62;
  }

  @override
  int bermAngleModeCmd() {
    return 67;
  }
}

class _E25CmdV1 extends _E25Cmd {
  @override
  int autoHeadlightCmd() {
    return 47;
  }

  @override
  int autoScreenOffCmd() {
    return 61;
  }

  @override
  int autoHeadlightBrightnessThrCmd() {
    return 42;
  }

  @override
  int brightnessOfHeadlightCmd() {
    return 43;
  }

  @override
  int calibrateImuCmd() {
    return 66;
  }

  @override
  int deviceNameCmd() {
    return 12;
  }

  @override
  int headlightOnOffCmd() {
    return 64;
  }

  @override
  int lightEffectIdCmd() {
    return 45;
  }

  @override
  int passwordCmd() {
    return 10;
  }

  @override
  int passwordTypeCmd() {
    return 11;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 63;
  }

  @override
  int assistBalanceCmd() {
    return 0;
  }

  @override
  int soundWaveCmd() {
    return 57;
  }

  @override
  int soundWaveSensitivityCmd() {
    return 56;
  }

  @override
  int speedThrOfLowHighBeamSwitchCmd() {
    return 0;
  }

  @override
  int speedingBrakingCmd() {
    return 66;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 64;
  }

  @override
  int transportationModeCmd() {
    return 50;
  }

  @override
  int usbPowerCmd() {
    return 60;
  }

  @override
  int lightEffectModeCmd() {
    return 51;
  }

  @override
  int autoLowHighBeamOnOffCmd() {
    return 47;
  }

  @override
  int bmsCellsVoltageCmd() {
    return 2;
  }

  @override
  int bmsDateCmd() {
    return 3;
  }

  @override
  int bmsFixedInfoCmd() {
    return 4;
  }

  @override
  int bmsLogCmd() {
    return 5;
  }

  @override
  int bmsRealTimeInfoCmd() {
    return 1;
  }
}

class _E25CmdV2 extends _E25CmdV1 {
  int speedUnitCmd() => 70;

  int daytimeRunningLightCmd() => 68;

  @override
  int speedThrOfLowHighBeamSwitchCmd() {
    return 48;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 63;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 64;
  }

  @override
  int assistBalanceCmd() {
    return 65;
  }

  @override
  int speedingBrakingCmd() {
    return 66;
  }

  @override
  int headlightOnOffCmd() {
    return 80;
  }

  @override
  int playSoundItemCmd() {
    return 81;
  }

  @override
  int calibrateImuCmd() {
    return 82;
  }

  @override
  int disableChargeDangerAlertCmd() {
    return 83;
  }
}

class PublicE25CmdV2 extends _E25CmdV2 {}
